package com.lazy.lib.util;

/**
 * 字节操作的工具
 *
 * @author grind
 * @date Mar 6, 2014 11:42:36 AM
 * @version 1.0
 */
public class ByteUtil {
    

    /**
     * 将字节流作为十六进制数据输出，方便在日志中阅评
     * @param bArray
     * @return 
     */
    public static String formatHexStr(byte[] bArray) {
        return formatHexStr(bArray, bArray.length);
    }
    

    /**
     * 将字节流作为十六进制数据输出，方便在日志中阅评
     * @param bArray
     * @return
     */
    /*
    public static String formatHexStr(byte[] bArray, int length) {
        StringBuilder sb = new StringBuilder();
        sb.append("\n");
        sb.append("00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F    TXT\n-------------------------------------------------------------------\n");
        byte[] t = new byte[16];
        for(int i = 0; i<= length /16; i++){
            if (i == length /16) {
                System.arraycopy(bArray, i * 16, t, 0, length - i * 16);
                for (int j = length - i * 16; j < 16; j++) {
                    t[j] = (byte) 0xFE;
                }
            }else {
                System.arraycopy(bArray, i * 16, t, 0, 16);
            }
            String hex = toHexStr(t);
            StringBuilder sb1 = new StringBuilder();
            for (int x = 0; x< hex.length(); x +=2) {
                sb1.append(hex.substring(x, x +2)).append(" ");
            }
            sb.append(sb1.toString()).append("   ").append(replaceContorlchar(t)).append("\n");
        }
        return sb.toString();
    }
    */

    /**
     * 将字节流作为十六进制数据输出，方便在日志中阅评
     * @param bArray
     * @return
     */
    public static String formatHexStr(byte[] bArray, int length) {
        return formatHexStr(bArray, 0, length);
    }
    /**
     * 将字节流作为十六进制数据输出，方便在日志中阅评
     * @param bArray
     * @return
     */
    public static String formatHexStr(byte[] bArray, int offset, int length) {
        StringBuilder sb = new StringBuilder();
        String sTemp;
        if (length > bArray.length - offset) {
            length = bArray.length - offset;
        }
        for(int i = 0; i< length; i++){
            if (0 == i%16) {
                sb.append("\n");
            } else {
                sb.append(" ");
            }
            sTemp = Integer.toHexString(0xFF & bArray[i+offset]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }

        sb.append("\n");
        return sb.toString();
    }
    
    /**
     * 将字节流作为十六进制数据输出，带有ascii的输出
     * @param bArray
     * @return
     */
    public static String formatHexStrWithNote(byte[] bArray, int length) {
        StringBuilder sb = new StringBuilder();
        byte[] t = new byte[16];
        int len = 16;
        for(int i = 0; i<= length /16; i++){
            if (i == length /16) {
                System.arraycopy(bArray, i * 16, t, 0, length - i * 16);
                len = length -i*16;
            }else {
                System.arraycopy(bArray, i * 16, t, 0, 16);
                len = 16;
            }
            String hex = toHexStr(t,0,len," ");
            StringBuilder sb1 = new StringBuilder();
            sb1.append(hex);
            if (len < 16) {
				for (int x = 0; x < 16 - len; x++) {
					sb1.append("  ");
				}
            }

            sb.append(sb1.toString()).append("   ").append(replaceContorlchar(t)).append("\n");
        }
        return sb.toString();
    }

    // 将不可显示字符换成?
    private static String replaceContorlchar(byte[] a) {
        for (int i = 0; i < a.length; i++) {
            if (a[i] < 0x20 || a[i] == 0x7F) {
                a[i] = (byte)0x3F;
            }
        }
        return new String(a);
    }

    /**
     * 将字节流作为十六进制数据在一行内输出，
     * @param bArray
     * @return
     */
    public static String formatHexStrOneLine(byte[] bArray) {
        StringBuilder sb = new StringBuilder();
        String hex = toHexStr(bArray);    
        sb.append(hex.toString()).append("\n");
        return sb.toString();
    }

    /**
     * 十六进制字符串转换成字节数组
     * @param hex like : 32 55 A0
     * @param delimit 字符串中显示的分割符号
     * @return
     */
    public static byte[] fromHexString(String hex, String delimit) {
        String srcHex = null;
        if (delimit == null || delimit.isEmpty()) {
            srcHex = hex;
        } else {
            srcHex = hex.replace(delimit, "");
        }
        
        return fromHexStr(srcHex);
    }

    /**
     * 十六进制字符串转换成字节数组
     * @param hex like : 32 55 A0
     * @return
     */
    public static byte[] fromHexStr(String hex) {
        hex = hex.toUpperCase();
        int len = (hex.length() / 2);
        byte[] result = new byte[len];
        char[] achar = hex.toCharArray();
        for (int i = 0; i < len; i++) {
            int pos = i * 2;
            result[i] = (byte) (toByte(achar[pos]) << 4 | toByte(achar[pos + 1]));
        }
        return result;
    }
    
    /**
     * 把字节数组转换成16进制字符
     * @param bArray
     * @return
     */
    public static final String toHexStr(byte[] bArray) {
        return toHexStr(bArray, null);
    }
    
    /**
     * 把字节数组转换成16进制字符, 中间用delimit隔开
     * @param bArray
     * @return
     */
    public static final String toHexStr(byte[] bArray, String delimit) {
        return toHexStr(bArray, 0, bArray.length, delimit);
    }

    /**
     * 把字节数组转换成16进制字符, 中间用delimit隔开
     * @param bArray
     * @param index 起始地址
     * @param len 长度
     * @param delimit
     * @return
     */
    public static final String toHexStr(byte[] bArray, int index, int len, String delimit) {
        StringBuffer sb = new StringBuffer(bArray.length);
        String sTemp;
        int endIndex = len + index;
        if (endIndex > bArray.length) {
            endIndex = bArray.length;
        }
        for (int i = index; i < endIndex; i++) {
            sTemp = Integer.toHexString(0xFF & bArray[i]);
            if (sTemp.length() < 2) {
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
            if (delimit != null && !delimit.isEmpty()) { sb.append(delimit);}
        }
        return sb.toString();
    }

    public static byte toByte(char c) {
        byte b = (byte) "0123456789ABCDEF".indexOf(c);
        return b;
    }

    /**
     * 设置byte的index位（bit）的值为1
     * @param b
     * @param index
     * @return
     */
    public static byte setBitToByte(byte b, int index){
        b |= 0x1<<index;
        return b;
    }
    
    
    /**
     * 设置short的index位（bit）的值为1
     * @param b
     * @param index
     * @return
     */
    public static short setBitToShort(short b, int index){
        b |= 0x1<<index;
        return b;
    }

    public static void main(String[] args){

        String str = "7E 02 00 00 26 00 32 68 88 20 01 19 4F 00 00 00 80 00 00 00 03 01 E8 A8 72 07 14 5E 9D 00 40 00 00 00 00 14 03 04 11 36 33 01 04 00 00 1F 9C 03 02 00 00 21 7E";

        byte[] result = fromHexString(str, " ");
        System.out.println(formatHexStr(result));
        System.out.println(toHexStr(result));
    }

}
